<template>
    <div class="content">
      <div class="content-head">
        <div class="head-left">
            <el-button type="primary" size="small" icon="el-icon-plus" style="margin-right:20px;" @click="createUser">创建用户</el-button>
            <el-popover placement="top-start" width="100" trigger="hover">
                <el-button type="text" @click="downloadTemplate">下载导入模板</el-button>
                <el-button type="text" @click="importExcel">导入数据</el-button>
                <el-button slot="reference" type="primary" size="small">导入管理<i class="el-icon-arrow-down el-icon--right"></i></el-button>
            </el-popover>
        </div>
        <div class="head-right">
            <div class="right-search">
                <span class="search-tip">用户名</span>
                <el-input v-model="formData.username" type="text" size="small" clearable placeholder="输入用户名搜索"></el-input>
            </div>
            <div class="btns">
                <el-button type="success" size="small" icon="el-icon-search" @click="search_btn">查询</el-button>
                <el-button type="primary" size="small" icon="el-icon-refresh-left" @click="reset_btn">重置</el-button>
            </div>
        </div>
      </div>
      <div class="content-table">
        <el-table :data="tableData" v-loading="tableLoading" style="width: 100%;" :max-height="tableMaxHeight">
            <el-table-column prop="userName" label="用户名" width="150"></el-table-column>
            <el-table-column prop="name" label="姓名" width="150"></el-table-column>
            <el-table-column prop="sexName" label="性别" width="100"></el-table-column>
            <el-table-column prop="age" label="年龄" width="120"></el-table-column>
            <el-table-column prop="mobile" label="手机号" width="150"></el-table-column>
            <el-table-column prop="" label="角色" width="">
              <template slot-scope="{ row, $index }">
                <el-tag v-for="item,index in row.roles" :key="index" style="margin:0 5px 3px 0;">{{ item.roleName }}</el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="createdDate" label="创建时间" width="160"></el-table-column>
            <el-table-column prop="" label="操作" width="200"  fixed="right">
              <template slot-scope="{ row, $index }">
                  <el-button type="text" @click="edit_btn(row)" :disabled="row.interned">编辑</el-button>
                  <el-button type="text" @click="examine_btn(row)">查看</el-button>
                  <el-button type="text" @click="resetPwd_btn(row)">重置密码</el-button>
                  <el-popconfirm title="确定删除该用户吗？" @onConfirm="delete_btn(row)">
                    <el-button type="text" slot="reference" style="margin-left:10px;" :disabled="row.interned">删除</el-button>
                  </el-popconfirm>
              </template>
            </el-table-column>
        </el-table>
      </div>
      <div class="content-footer">
        <el-pagination @size-change="handleSizeChange"  @current-change="handleCurrentChange" :current-page="currentPage" :page-sizes="[10,20,30,40,50]" :page-size="pageSize" background layout="prev, pager, next,total, sizes, jumper" :total="total"></el-pagination>
      </div>
      <!-- dialog -->
      <div v-if="dialogVisible">
        <el-dialog :title="dialogTitle" :visible.sync="dialogVisible"  @close="dialogCancel_btn" :close-on-click-modal="false" class="dialog-content" width="60%">
          <el-form label-position="right" label-width="80px" ref="dialogForm" :model="dialogForm" :rules="dialogFormRules" size="small" :disabled="dialogState === 1" style="width:80%;">
            <el-form-item label="用户名" prop="username">
              <el-input v-model="dialogForm.username" placeholder="请输入用户名，支持字母、数字、_下划线，长度不少于5位"></el-input>
            </el-form-item>
            <el-form-item label="姓名" prop="name">
              <el-input v-model="dialogForm.name" placeholder="请输入姓名"></el-input>
            </el-form-item>
            <el-form-item label="性别" prop="sex">
              <el-radio-group v-model="dialogForm.sex">
                <el-radio :label="0">女</el-radio>
                <el-radio :label="1">男</el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="年龄" prop="age">
              <el-input v-model="dialogForm.age" @input="dialogForm.age = String(dialogForm.age).replace(/[^0-9]/g,'')" placeholder="请输入年龄"></el-input>
            </el-form-item>
            <el-form-item label="手机号" prop="mobile">
              <el-input v-model="dialogForm.mobile" @input="dialogForm.mobile = String(dialogForm.mobile).replace(/[^0-9]/g,'')" placeholder="请输入手机号码"></el-input>
            </el-form-item>
            <el-form-item label="角色" prop="roleList">
              <el-checkbox-group v-model="dialogForm.roleList">
                <el-checkbox v-for="item,index in allRoleList" :key="index" :label="item.roleName"></el-checkbox>
              </el-checkbox-group>
            </el-form-item>
            <el-form-item label="创建时间" v-if="dialogState !== 0">
              <el-input v-model="dialogForm.createdDate" :disabled="dialogState === 2"></el-input>
            </el-form-item>
            <el-form-item label="" v-if="dialogState === 0">
              <span class="form-item-tip">注:新创建的用户初始密码为:123456</span>
            </el-form-item>
          </el-form>
          <span slot="footer" class="dialog-footer" v-if="dialogState !== 1">
            <el-button size="small" @click="dialogCancel_btn">取 消</el-button>
            <el-button type="primary" size="small" @click="dialogConfirm_btn">确 定</el-button>
          </span>
        </el-dialog>
      </div>
      <!-- 重置密码dialog -->
      <el-dialog title="重置密码" :visible.sync="resetPwdDialogVisible" :close-on-click-modal="false" @close="resetPwdDialogCancel_btn">
          <el-form label-position="right" label-width="80px" ref="resetPwdForm" :model="resetPwdForm" :rules="resetPwdFormRules" size="small" style="width:80%;">
            <el-form-item label="新密码" prop="newPwd">
              <el-input v-model="resetPwdForm.newPwd" placeholder="请输入新密码"></el-input>
            </el-form-item>
          </el-form>
          <span slot="footer" class="dialog-footer">
            <el-button size="small" @click="resetPwdDialogCancel_btn">取 消</el-button>
            <el-button type="primary" size="small" @click="resetPwdDialogConfirm_btn">确 定</el-button>
          </span>
      </el-dialog>
    </div>
  </template>
  
  <script>
  import { reqRoleList, reqUserList, reqUpdateUserPassword, reqUpdateUser, reqDeleteUser, reqCreateUser, reqDownloadUserImportTemplate, reqUploadUserInfoExcel, reqUserListByUserName } from "@/api/user.js";
  export default {
    data() {
      const validate1 = (rule, value, callback) => {
        const regex = /^[a-zA-Z0-9_]{5,20}$/;
        if (value.trim() === '') {
          callback(new Error('请输入用户名'));
        } else if(!regex.test(value)) {
          callback(new Error("请输入合法的用户名，支持字母、数字和下划线，长度5-20位"));
        } else if (regex.test(value)){
          callback();
        }
      };
      const validate2 = (rule, value, callback) => {
        if (value.trim() === '') {
          callback(new Error('请输入姓名'));
        } else if(value.trim().length < 2 || value.trim().length > 30) {
          callback(new Error("姓名应为2-30个字符"));
        } else {
          callback();
        }
      };
      const validate3 = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请选择性别'));
        } else {
          callback();
        }
      };
      const validate4 = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请输入年龄'));
        } else if(Number(value) > 130){
          callback(new Error('您是吃了唐僧吗'));
        } else if(Number(value) < 1){
          callback(new Error('年龄太小了'));
        } else {
          callback();
        }
      };
      const validate5 = (rule, value, callback) => {
        if (value.trim() === '') {
          callback(new Error('请输入手机号'));
        } else if(value.trim().length !== 11){
          callback(new Error("手机号码格式错误"));
        } else {
          callback();
        }
      };
      const validate6 = (rule, value, callback) => {
        if (value.length === 0) {
          callback(new Error('请勾选至少一个角色'));
        } else {
          callback();
        }
      };
      const validate7 = (rule, value, callback) => {
        const regex = /^[a-zA-Z0-9_]{6,}$/;
        if (value.trim() === '') {
          callback(new Error('请输入新密码'));
        } else if(!regex.test(value)){
          callback(new Error('密码只能为字母、数字和下划线_，长度不能少于6位'));
        } else {
          callback();
        }
      };
      return {
        formData:{
          username:""
        },
        dialogForm:{
          id:"",
          username:"",
          name:"",
          sex:"",
          age:"",
          mobile:"",
          roleList:[],
          createdDate:""
        },
        dialogFormRules:{
          username: [{ validator: validate1, trigger: 'blur' }],
          name: [{ validator: validate2, trigger: 'blur' }],
          sex: [{ validator: validate3, trigger: 'change' }],
          age: [{ validator: validate4, trigger: 'blur' }],
          mobile: [{ validator: validate5, trigger: 'blur' }],
          roleList: [{ validator: validate6, trigger: 'change' }]
        },
        resetPwdForm:{
          id:"",
          newPwd:""
        },
        resetPwdFormRules:{
          newPwd: [{ validator: validate7, trigger: 'blur' }],
        },
        tableData:[],
        currentPage:1,
        pageSize:10,
        total:0,
        dialogVisible:false,  //dialog弹出层
        resetPwdDialogVisible:false,
        dialogState:0,  //dialog弹出层状态 0-添加 1-查看 2-编辑
        tableLoading:false,
        tableMaxHeight:0,
        allRoleList:[]
      }
    },
    computed:{
      dialogTitle(){
        let state = this.dialogState;
        if(state === 0){
          return "创建用户";
        }
        if(state === 1){
          return "查看用户";
        }
        if(state === 2){
          return "编辑用户";
        }
      },
    },
    mounted(){
      //动态设置table表格的max-height属性
      window.addEventListener("resize",this.setTableMaxHeight);
      this.setTableMaxHeight();
      this.getUserList();
      this.getAllRoleList();
    },
    beforeDestroy(){
        window.removeEventListener("resize",this.setTableMaxHeight);
    },
    methods:{
      //分页查询所有的角色信息
      getAllRoleList(){
        reqRoleList(1,100).then(response => {
          if(response.data.code === 200){
            let tmp = response.data.data.content;
            this.allRoleList = tmp.map(item => {
              return {id:item.id, roleName:item.roleName, menuIds:item.menuIds};
            })
          }
          console.log('分页获取角色列表api',response);
        }).catch(error => {
          this.$message({type:"error",message:"角色列表信息获取失败"});
        })
      },
      //分页获取所有的用户列表
      getUserList() {
        let page = this.currentPage;
        let size = this.pageSize;
        this.tableLoading = true;
        reqUserList(page, size).then(response => {
          const { code , data } = response.data;
          if(code === 200){
            this.tableData = data.content.map(item => {
              let tmp = "";
              if(item.sex === 0){
                tmp = '女';
              } else if(item.sex === 1){
                tmp = '男';
              }
              return {...item,sexName:tmp};
            });
            this.total = data.totalElements;
          }
          this.tableLoading = false;
          console.log("分页获取所有用户列表信息",response);
        }).catch(error => {
          this.$message({type:"error",message:"获取用户列表信息失败"});
          this.tableLoading = false;
        })
      },
      createUser(){
        this.dialogState = 0;
        this.dialogVisible = true;
      },
      downloadTemplate(){
        this.$confirm("即将下载导入用户信息Excel模板", '提示', { confirmButtonText: '确定', cancelButtonText: '取消',type: 'warning'})
          .then(async () => {
              let res = await reqDownloadUserImportTemplate();
              if (res.status === 200) {
                  let blob = res.data;
                  let url = window.URL.createObjectURL(blob, { type: 'application/zip' });
                  const aLink = document.createElement('a');
                  aLink.href = url;
                  let timestamp = new Date().getTime();
                  aLink.setAttribute('download', '导入用户信息模板_' + timestamp);
                  document.body.appendChild(aLink);
                  aLink.click();
                  document.body.removeChild(aLink);
                  this.$message.success('模板下载成功!');
                  this.templateDownloadBtnLoading = false;
              } else {
                  this.$message.error('模板下载失败,请重试!');
              }
          }).catch(() => {
              this.$message({type:"info",message:"取消模板下载!"});
          });
      },
      importExcel(){
        const _this = this;
        const divBox = document.querySelector(".head-left");
        let inputDom = document.createElement("input");
        inputDom.style.display = 'none';
        inputDom.type = 'file';
        divBox.appendChild(inputDom);
        inputDom.click();
        inputDom.onchange = async function (event) {
          let file = event.target.files[0];
          let fileType = file.name.substring(file.name.lastIndexOf("."), file.name.length);
          let fileSize = file.size / 1024 / 1024;  //转为MB
          if (fileType !== '.xlsx' && fileType !== '.xls') {
              _this.$message({ type: 'warning', message: "请选择excel文件!" });
              return;
          }
          if (fileSize > 10) {
              _this.$message({ type: 'warning', message: "文件大小不能超过10MB!" });
              return;
          }
          //准备formData
          const formData = new FormData();
          formData.append('file', file);
          try{
              let res = await reqUploadUserInfoExcel(formData);
              if (res.data.code === 200) {
                  _this.$message({ type: "success", message: "文件上传成功!" });
              } else {
                  _this.$message({ type: "error", message: "文件上传失败，请重试!" });
              }
          } catch(err) {
              _this.$alert("用户导入失败，检查导入数据格式要求是否和模板一致后重试!", '警告', { confirmButtonText: '确定', callback: action => {}});
          }
          _this.getUserList();
        }
        divBox.removeChild(inputDom);  //移除input
      },
      //查询重置导出按钮
      search_btn(){
        const username = this.formData.username;
        const page = this.currentPage;
        const size = this.pageSize;
        if(username.trim() === ""){
          this.$message({type:"info",message:"搜索条件为空"});
          return;
        }
        this.tableLoading = true;
        reqUserListByUserName(page,size,username).then(response => {
          const { code , data } = response.data;
          if(code === 200){
            this.tableData = data.content.map(item => {
              return {...item,sexName:item.sex === 0 ? '女' : '男'};
            });
            this.total = data.totalElements;
          }
          this.tableLoading = false;
          console.log('根据用户名模糊查询用户信息',response);
        }).catch(error => {
          this.$message({type:"error",message:"用户查询失败"});
        })
      },
      reset_btn(){
        this.formData.username = "";
        this.currentPage = 1;
        this.pageSize = 10;
        //重新获取表格数据
        this.getUserList();
      },
      export_btn() {
        this.$confirm('即将导出当前内容', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'})
            .then(async () => {
                this.exportBtnLoading = true;
                let res = await reqExportReportsWorkOrder();
                if (res.status === 200) {
                    let blob = res.data;
                    let url = window.URL.createObjectURL(blob,{type: 'application/zip'});
                    const aLink = document.createElement('a');
                    aLink.href = url;
                    let timestamp = new Date().getTime();
                    aLink.setAttribute('download', '工单报工信息列表_' + timestamp);
                    document.body.appendChild(aLink);
                    aLink.click();
                    document.body.removeChild(aLink);
                    this.$message.success('导出成功');
                    this.exportBtnLoading = false;
                } else {
                    this.$message.error('导出失败,请重试');
                    this.exportBtnLoading = false;
                }
            }).catch(() => {
                this.$message({type: 'info', message: '已取消导出!'});          
            });
      },
      //分页器
      handleCurrentChange(curPage){
        this.currentPage = curPage;
        //重新获取数据
        this.getUserList();
      },
      handleSizeChange(pageSize){
        this.pageSize = pageSize;
        //重新获取数据
        this.getUserList();
      },
      //表格相关的按钮
      edit_btn(row){
        this.dialogState = 2;
        this.dialogVisible = true;
        this.dialogForm.id = row.id;
        this.dialogForm.username = row.userName;
        this.dialogForm.name = row.name;
        this.dialogForm.sex = row.sex;
        this.dialogForm.age = row.age;
        this.dialogForm.mobile = row.mobile === null ? "" : row.mobile;
        this.dialogForm.roleList = row.roles.map(item => item.roleName);
        this.dialogForm.createdDate = row.createdDate;
      },
      examine_btn(row){
        this.dialogState = 1;
        this.dialogVisible = true;
        this.dialogForm.username = row.userName;
        this.dialogForm.name = row.name;
        this.dialogForm.sex = row.sex;
        this.dialogForm.age = row.age;
        this.dialogForm.mobile = row.mobile;
        this.dialogForm.roleList = row.roles.map(item => item.roleName);
        this.dialogForm.createdDate = row.createdDate;
      },
      resetPwd_btn(row){
        this.resetPwdDialogVisible = true;
        this.resetPwdForm.id = row.id;
      },
      delete_btn(row){
        reqDeleteUser(row.id).then(response => {
          if(response.data.code === 200){
            this.$message({type:"success",message:"用户删除成功"});
            //更新列表数据
            this.getUserList();
          }
          console.log('管理员删除用户api',response);
        }).catch(error => {
          this.$message({type:"error",message:"用户删除失败:" + error.response.data.message});
        })
      },
      //dialog相关按钮
      dialogCancel_btn(){
        this.dialogVisible = false;
        this.dialogState = 0;
        this.$refs.dialogForm.resetFields();
        this.dialogForm.id = "";
        this.dialogForm.username = "";
        this.dialogForm.name = "";
        this.dialogForm.sex = "";
        this.dialogForm.age = "";
        this.dialogForm.mobile = "";
        this.dialogForm.roleList = [];
        this.dialogForm.createdDate = "";
      },
      dialogConfirm_btn(){
        let isValidate = false;
        this.$refs.dialogForm.validate((validate) => {
          if(validate){
            isValidate = true;
          } else{
            isValidate = false;
          }
        })
        if(!isValidate){
          this.$message({type:"info",message:"请将表单填写完整"});
          return;
        }
        //准备参数
        const {id,username,name,sex,age,mobile,roleList} = this.dialogForm;
        let roles = this.allRoleList.filter(item => roleList.includes(item.roleName));
        const parameters = {userName:username,name,sex,age,mobile,roles};
        if(this.dialogState === 0){
          //添加
          reqCreateUser(parameters).then(response => {
            if(response.data.code === 200){
              this.$message({type:"success",message:"用户创建成功"});
              //关闭dialog
              this.dialogCancel_btn();
              //重新请求列表数据
              this.getUserList();
            }
            console.log('添加用户api',response);
          }).catch(error => {
            this.$message({type:"error",message:"用户创建失败:" + error.response.data.message});
          })
        } else if(this.dialogState === 2){
          //编辑
          parameters.id = id;
          reqUpdateUser(parameters).then(response => {
            if(response.data.code === 200){
              this.$message({type:"success",message:"用户更新成功"});
              //关闭dialog
              this.dialogCancel_btn();
              //重新请求列表数据
              this.getUserList();
            }
            console.log('更新用户api',response);
          }).catch(error => {
            this.$message({type:"error",message:"用户信息更新失败:" + error.response.data.message});
          })
        }
      },
      //重置密码的dialog确定取消按钮
      resetPwdDialogCancel_btn(){
        this.resetPwdDialogVisible = false;
        this.$refs.resetPwdForm.resetFields();
        this.resetPwdForm.id = "";
        this.resetPwdForm.newPwd = "";
      },
      resetPwdDialogConfirm_btn(){
        this.$refs.resetPwdForm.validate((validate) => {
          if(validate){
            const { id, newPwd } = this.resetPwdForm;
            reqUpdateUserPassword({id,password:newPwd}).then(response => {
              if(response.data.code === 200){
                this.$message({type:"success",message:"用户密码重置成功"});
                //关闭重置密码dialog
                this.resetPwdDialogCancel_btn();
              }
              console.log('管理员修改用户密码api',response);
            }).catch(error => {
              this.$message({type:"error",message:"用户密码重置失败:" + error.response.data.message});
            })
          }
        })
      },
      //格式化时间
      formatDate(val,type){
          let date = new Date(val);
          let year = date.getFullYear();
          let month = date.getMonth() + 1;
          let day = date.getDate();
          let h = date.getHours();
          let m = date.getMinutes();
          let s = date.getSeconds();
          if(type === 0){
              return year + "-" + this.addZero(month) + "-" + this.addZero(day) + " " + this.addZero(h) + ":" + this.addZero(m) + ":" + this.addZero(s);
          } else if (type === 1){
              return year + "-" + this.addZero(month) + "-" + this.addZero(day);
          } else if (type === 2){
              return this.addZero(h) + ":" + this.addZero(m) + ":" + this.addZero(s);
          } else if (type === 3){
              return year + "-" + this.addZero(month) + "-" + this.addZero(day) + " 00:00:00";
          }
      },
      addZero(val){
          return val > 9 ? val : "0" + val;
      },
      //动态设置table表格的max-height属性
      setTableMaxHeight(){
        let dom = document.querySelector(".content-table");
        this.$nextTick(() => {
            this.tableMaxHeight = dom.offsetHeight - 10;
        })
      }
    }
  }
  </script>
  
  <style lang='scss' scoped>
  .content{
    width: 100%;
    height: calc(100vh - 50px);
    display: flex;
    flex-direction: column;
    padding: 10px 20px;
    box-sizing: border-box;
  
    .content-head{
      height: 10%;
      display: flex;
      justify-content: space-between;
      align-items: center;
      .head-left{
        display: flex;
      }
      .head-right{
        display: flex;
        align-items: center;
        .right-search{
            display: flex;
            align-items: center;
            margin-right: 20px;
            .search-tip{
                width: 80px;
                margin-right: 5px;
                font-size: 14px;
                color: #9195a3;
            }
        }
      }
    }
    .content-table{
      margin: 10px 0;
      height: 80%;
    }
    .content-footer{
      height: 10%;
      display: flex;
      justify-content: flex-end;
    }
  }
  .dialog-content{
    .form-item-tip{
      font-size: 12px;
      color: #c0c4cc;
    }
  }
  </style>